#pragma once

#include "ui.hpp"


/**
 * @brief 读数界面
 *
 */
class CountScreen : public beef::InterfaceBase {
   private:
    bool _is_continuous = false;  // 当前为连测模式，否则单测
    bool _mode_change_waiting_confirm = false;
    bool _is_already_continuous = false;
    bool _mode_changed = false;
    bool _retry = false;
    bool _stop_mode = false;

    bool _do_count = false;
    uint8_t _ret_code = 0;

    bool _no_mode_key = false;  // 禁止响应模式切换按键和OK

    // uint32_t _unit_factor = 0;

    data_basic::RingBuffer<Count, 5> _count_history;

    void draw_count_mode() {
        if (_stop_mode && !_mode_change_waiting_confirm) {
            draw_mode("停止");
        }
        else {
            if (_is_continuous) {
                draw_mode("连测");
            }
            else {
                draw_mode("单测");
            }
        }
    }

    void show_count_history() {
        uint8_t y = 23;
        uint8_t size = _count_history.size();
        uint8_t i = _count_history.back_index();
        u8g2.setFont(SMALL_TEXT_FONT);

        while (size > 0) {
            i = _count_history.dec_index(i);
            --size;
            u8g2.setCursor(25, y);
            auto d = _count_history.value(i);
            show_meters(d.m, d.mm);
            if (d.m < 100) {
                u8g2.print("    ");
            }

            y += 8;
        }
    }

    void push_history(uint32_t count) {
        auto m = static_cast<uint16_t>(count / 1000);
        auto mm = static_cast<uint16_t>(count % 1000);
        _count_history.push_back({m, mm});
    }

    virtual void poll() override {
        bool send_buffer = false;

        if (!_no_mode_key) {
            if (button_up.clicked() || button_down.clicked()) {
                if (!_mode_changed) {
                    _is_continuous = !_is_continuous;
                    if (_is_continuous != _is_already_continuous || _stop_mode) {
                        _mode_change_waiting_confirm = true;
                        show_ask("OK?");
                        //  Serial.print("OK?\n");
                    }
                    else {
                        _mode_change_waiting_confirm = false;
                        show_ask(nullptr);
                    }

                    draw_count_mode();
                    send_buffer = true;
                }
            }
            else if (button_ok.clicked()) {
                if (_mode_change_waiting_confirm) {
                    // 点OK 确定切换模式
                    _mode_change_waiting_confirm = false;
                    _mode_changed = true;
                    show_ask(nullptr);
                    bkr.start_blink();
                    // TODO: show_waiting
                    send_buffer = true;
                }
                else if (!_is_already_continuous && !_do_count) {
                    // 点OK 触发一次单测
                    _do_count = true;
                    bkr.start_blink();
                    send_buffer = true;
                }
            }
        }

        // 任何时候都允许左右切换界面
        bool left = button_left.clicked();
        if (left) {
            _ret_code = NAVIGATION_LEFT;
            bkr.start_blink();
            send_buffer = true;
            reset_button_event();
        }

        refresh_screen_when(send_buffer, bkr.blink());
    }

    virtual int show() override {
        _no_mode_key = true;
        // 先读取设备信息，确定当前的模式和测量单位
        show_count(0, "LOAD");
        u8g2.setFont(CHS_FONT);
        u8g2.drawUTF8(20, 37, "读取配置");
        bkr.start_blink();
        u8g2.sendBuffer();

        // 持续尝试读取设备信息
        uint16_t config_buffer[6];
        // 读取设备信息的阶段，超时时间短一点
        set_response_timeout(MODBUS_CONFIG_TIMEOUT);

        while (1) {
            tick();

            // 可以取消操作，切换去其他界面
            if (_ret_code != 0) {
                return _ret_code;
            }

            bool r = read_config(this, slave_address(), config_buffer);
            if (!r) {
                show_count(0, "RETRY");
                u8g2.sendBuffer();
            }
            else {
                // 获取设备模式和距离单位
                auto mode = config_buffer[1];
                // auto unit = config_buffer[5];

                // Serial.print("CONFIG: ");
                // for(auto h : config_buffer) {
                //     Serial.print(h);
                //     Serial.print(", ");
                // }
                // Serial.print("\n");

                _stop_mode = false;

                if (mode == static_cast<uint8_t>(sensor_mode::单测)) {
                    _is_already_continuous = false;
                    _is_continuous = false;
                }
                else if (mode == static_cast<uint8_t>(sensor_mode::连测)) {
                    _is_already_continuous = true;
                    _is_continuous = true;
                }
                else {
                    _stop_mode = true;
                }

                // if (unit == 1 || unit == 10 || unit == 1000) {
                //     _unit_factor = unit;
                // }
                // else {
                //     _unit_factor = 1;
                // }

                break;
            }
        }

        set_response_timeout(MODBUS_COUNT_TIMEOUT);
        bkr.stop_blink();
        _no_mode_key = false;
        uint32_t count = -1;
        const char *alt = "OK";
        clear_box(20, 25, 60, 20);  // 清除掉“读取配置”
        draw_count_mode();
        show_count(0, alt);
        show_period_time(连测周期());
        u8g2.sendBuffer();

        while (1) {
            tick();

            // u8g2.clearBuffer();

            u8g2.setFont(CHS_FONT);

            if (_mode_changed || _retry) {
                // 发送命令，切换模式
                // 如果在单测模式，通信超时应该设置的长一点
                // 或者把连测和单测超时设置成一样的
                bool r = false;
                if (_is_continuous) {
                    r = write_mode(this, slave_address(), sensor_mode::连测);
                }
                else {
                    r = write_mode(this, slave_address(), sensor_mode::单测);
                }

                _mode_changed = false;

                if (!r) {
                    alt = "RETRY";
                    _retry = true;
                }
                else {
                    alt = "OK";
                    _retry = false;
                    _is_already_continuous = _is_continuous;
                    _do_count = false;
                    _stop_mode = false;
                    // adjust_timeout();
                    bkr.stop_blink();
                }
            }
            else if (_stop_mode) {
                alt = "STOP";
            }
            else {
                if (_is_already_continuous || _do_count) {
                    if (count < 65535) {
                        push_history(count);
                    }

                    bool r = read_u32_from(this, slave_address(), 0, &count);

                    if (!r) {
                        count = -1;
                        alt = "ERR";
                    }
                    else {
                        alt = nullptr;
                        // count *= _unit_factor;
                    }

                    if (_do_count) {
                        _do_count = false;
                        bkr.stop_blink();
                    }
                }
            }

            show_count(count, alt);
            show_count_history();
            u8g2.sendBuffer();

            if (_ret_code != 0) {
                // 退出界面前将最新的读数压入历史，之后返回时不会丢失读数
                if (count < 65535) {
                    push_history(count);
                }
                return _ret_code;
            }

            if(_is_already_continuous) {
                auto t = 连测周期();
                if(t < 200) {
                    wait_for(200);
                }
                else {
                    wait_for(t);
                }
            }
            else {
                wait_for(500);
            }
            
        }

        return 0;
    }

    virtual void init(InterfaceBase *sub) override {
        reset_button_event();
        _mode_changed = false;
        _retry = false;
        _ret_code = 0;

        u8g2.clearBuffer();
        put_slave_address();
        draw_left_arrow();
        u8g2.sendBuffer();
    }

   public:
    CountScreen() {}
};